home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2002 #11 / Amiga Plus CD - 2002 - No. 11.iso / Tools / AmigaSystem / Scalos / GuiGFXLib / src / guigfx_picturemethod.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-10-28  |  53.3 KB  |  2,557 lines

  1. /*********************************************************************
  2. ----------------------------------------------------------------------
  3.  
  4.     guigfx_picturemethod
  5.  
  6. ----------------------------------------------------------------------
  7. *********************************************************************/
  8.  
  9. #include <render/render.h>
  10. #include <render/renderhooks.h>
  11. #include <utility/tagitem.h>
  12. #include <graphics/gfx.h>
  13. #include <graphics/view.h>
  14. #include <exec/memory.h>
  15.  
  16. #include <proto/render.h>
  17. #include <proto/graphics.h>
  18. #include <proto/exec.h>
  19. #include <proto/utility.h>
  20. #include <proto/dos.h>
  21. #include <proto/cybergraphics.h>
  22. #include <libraries/cybergraphics.h>
  23.  
  24. #include <guigfx/guigfx.h>
  25.  
  26. #include "guigfx_global.h"
  27. #include "guigfx_picturemethod.h"
  28. #include "guigfx_convolve.h"
  29.  
  30.  
  31. /*********************************************************************
  32. ----------------------------------------------------------------------
  33.  
  34.     BOOL InsertAlphaArray(pic)
  35.  
  36.     fügt einen ggf. vorhandenen, ausgelagerten
  37.     Alpha-Channel in das Bild ein. Es wird vorausgesetzt,
  38.     daß der ausgelagerte Alphachannel dieselbe Größe hat
  39.     wie das Bild.
  40.  
  41. ----------------------------------------------------------------------
  42. *********************************************************************/
  43.  
  44. BOOL InsertAlphaArray(PIC *pic)
  45. {
  46.     BOOL success = TRUE;
  47.  
  48.     ObtainSemaphore(&pic->semaphore);
  49.     
  50.     if (pic->alphapresent && pic->alphaarray)
  51.     {
  52.         /*
  53.          *    hier ist höchste Vorsicht geboten. PIC_Render
  54.          *    und InsertAlphaArray rufen sich gegenseitig auf!
  55.          */
  56.         
  57.         if (pic->pixelformat != PIXFMT_0RGB_32)
  58.         {
  59.             PIC_Render(pic, PIXFMT_0RGB_32, NULL);
  60.         }
  61.         
  62.         success = (pic->pixelformat == PIXFMT_0RGB_32);
  63.         
  64.         if (success)
  65.         {
  66.             if (pic->alphaarray)
  67.             {
  68.                 InsertAlphaChannel(pic->alphaarray, pic->width, pic->height, (APTR)pic->array, NULL);
  69.                 FreeRenderVec(pic->alphaarray);
  70.                 pic->alphaarray = NULL;
  71.             }
  72.         }
  73.     }
  74.  
  75.     ReleaseSemaphore(&pic->semaphore);
  76.  
  77.     return success;
  78. }
  79.  
  80.  
  81. /*********************************************************************
  82. ----------------------------------------------------------------------
  83.  
  84.     BOOL ExtractAlphaArray(pic)
  85.  
  86.     lagert einen ggf. im Bild vorhandenen Alphachannel in
  87.     ein externes Array aus.
  88.  
  89. ----------------------------------------------------------------------
  90. *********************************************************************/
  91.  
  92. BOOL ExtractAlphaArray(PIC *pic)
  93. {
  94.     BOOL success = TRUE;
  95.  
  96.     ObtainSemaphore(&pic->semaphore);
  97.     
  98.     if (pic->alphapresent && !pic->alphaarray)
  99.     {
  100.         if (pic->pixelformat == PIXFMT_0RGB_32)
  101.         {
  102.             success = FALSE;
  103.             if (pic->alphaarray = AllocRenderVec(MemHandler, pic->width * pic->height))
  104.             {
  105.                 ExtractAlphaChannel((APTR) pic->array,
  106.                     pic->width, pic->height, pic->alphaarray, NULL);
  107.                 success = TRUE;
  108.             }
  109.         }
  110.         #ifdef DEBUG
  111.         else
  112.         {
  113.             DB(kprintf("*** Illegal condition: where is the alpha-channel?\n"));
  114.         }
  115.         #endif
  116.     }
  117.  
  118.     ReleaseSemaphore(&pic->semaphore);
  119.  
  120.     return success;
  121. }
  122.  
  123.  
  124.  
  125. /*********************************************************************
  126. ----------------------------------------------------------------------
  127.  
  128.     DoPictureMethod(picture,method,argument,...)
  129.  
  130.     wendet eine Picture-Methode auf ein Bild an.
  131.  
  132. ----------------------------------------------------------------------
  133. *********************************************************************/
  134.  
  135. ULONG SAVE_DS ASM DoPictureMethodA(
  136.     REG(a0) APTR pic, 
  137.     REG(d0) ULONG method, 
  138.     REG(a1) ULONG *arg)
  139. {
  140.     ULONG result = FALSE;
  141.  
  142.     if(pic)
  143.     {    
  144.         switch (method)
  145.         {
  146.             case PICMTHD_CROP:
  147.                 result = PIC_Crop((PIC *) pic, arg[0], arg[1], arg[2], arg[3], (TAGLIST) &arg[4]);
  148.                 break;
  149.     
  150.             case PICMTHD_RENDER:
  151.                 result = PIC_Render((PIC *) pic, arg[0], (TAGLIST) &arg[1]);
  152.                 break;
  153.     
  154.             case PICMTHD_SCALE:
  155.                 result = PIC_Scale((PIC *) pic, arg[0], arg[1], (TAGLIST) &arg[2]);
  156.                 break;
  157.     
  158.             case PICMTHD_MIX:
  159.                 result = PIC_Mix((PIC *) pic, (PIC *) arg[0], (TAGLIST) &arg[1]);
  160.                 break;
  161.     
  162.             case PICMTHD_SETALPHA:
  163.                 result = PIC_SetAlpha((PIC *) pic, (UBYTE *) arg[0], arg[1], arg[2], (TAGLIST) &arg[3]);
  164.                 break;
  165.     
  166.             case PICMTHD_MIXALPHA:
  167.                 result = PIC_MixAlpha((PIC *) pic, (PIC *) arg[0], (TAGLIST) &arg[1]);
  168.                 break;
  169.  
  170.             case PICMTHD_MAPDRAWHANDLE:
  171.                 result = PIC_MapDrawHandle((PIC *) pic, (struct DrawHandle *) arg[0], (TAGLIST) &arg[1]);
  172.                 break;
  173.  
  174.             case PICMTHD_CREATEALPHAMASK:
  175.                 result = PIC_CreateAlphaMask((PIC *) pic, (ULONG) arg[0], (TAGLIST) &arg[1]);
  176.                 break;
  177.  
  178.             case PICMTHD_TINT:
  179.                 result = PIC_Tint((PIC *) pic, (ULONG) arg[0], (TAGLIST) &arg[1]);
  180.                 break;
  181.  
  182.             case PICMTHD_TINTALPHA:
  183.                 result = PIC_TintAlpha((PIC *) pic, (ULONG) arg[0], (TAGLIST) &arg[1]);
  184.                 break;
  185.  
  186.             case PICMTHD_TEXTURE:
  187.                 result = PIC_Texture((PIC *) pic, (PIC *) arg[0], (WORD *) arg[1], (TAGLIST) &arg[2]);
  188.                 break;
  189.  
  190.             case PICMTHD_SET:
  191.                 result = PIC_Set((PIC *) pic, (ULONG) arg[0], (TAGLIST) &arg[1]);
  192.                 break;
  193.  
  194.             case PICMTHD_INSERT:
  195.                 result = PIC_Insert((PIC *) pic, (PIC *) arg[0], (TAGLIST) &arg[1]);
  196.                 break;
  197.  
  198.             case PICMTHD_FLIPX:
  199.                 result = PIC_FlipX((PIC *) pic, (TAGLIST) &arg[0]);
  200.                 break;
  201.  
  202.             case PICMTHD_FLIPY:
  203.                 result = PIC_FlipY((PIC *) pic, (TAGLIST) &arg[0]);
  204.                 break;
  205.  
  206.             case PICMTHD_CHECKAUTODITHER:
  207.                 result = PIC_CheckDither((PIC *) pic, (DRAWHANDLE *) arg[0], (TAGLIST) &arg[1]);
  208.                 break;
  209.  
  210.             case PICMTHD_NEGATIVE:
  211.                 result = PIC_Negative((PIC *) pic, (TAGLIST) &arg[1]);
  212.                 break;
  213.  
  214.             case PICMTHD_AUTOCROP:
  215.                 result = PIC_AutoCrop((PIC *) pic, (TAGLIST) &arg[1]);
  216.                 break;
  217.  
  218.             case PICMTHD_CONVOLVE:
  219.                 result = PIC_Convolve((PIC *) pic, (KERNEL *) arg[0], (TAGLIST) &arg[1]);
  220.                 break;
  221.     
  222.             default:
  223.                 result = FALSE;
  224.         }
  225.     }
  226.  
  227.     return result;
  228. }
  229.  
  230.  
  231.  
  232. /*--------------------------------------------------------------------
  233.  
  234.     CreateAlphaMask (pic, rgb, tags)
  235.  
  236.     GGFX_SourceX        Default 0
  237.     GGFX_SourceY        Default 0
  238.     GGFX_SourceWidth    Bildbreite
  239.     GGFX_SourceHeight    Bildhöhe
  240.  
  241. --------------------------------------------------------------------*/
  242.  
  243. ULONG PIC_CreateAlphaMask(PIC *pic, ULONG rgb, TAGLIST tags)
  244. {
  245.     BOOL success = FALSE;
  246.  
  247.     ObtainSemaphore(&pic->semaphore);
  248.  
  249.     if (InsertAlphaArray(pic))
  250.     {
  251.         UWORD sourcewidth, sourceheight, sourcex, sourcey;
  252.  
  253.         sourcewidth = GetTagData(GGFX_SourceWidth, pic->width, tags);
  254.         sourceheight = GetTagData(GGFX_SourceHeight, pic->height, tags);
  255.         sourcex = GetTagData(GGFX_SourceX, 0, tags);
  256.         sourcey = GetTagData(GGFX_SourceY, 0, tags);
  257.  
  258.         /*
  259.          *    clipping
  260.     
  261.         sourcewidth = MIN(pic->width - sourcex, sourcewidth);
  262.         sourceheight = MIN(pic->height - sourcey, sourceheight);
  263.  
  264.          */
  265.  
  266.         success = TRUE;
  267.  
  268.         if (sourcewidth && sourceheight)
  269.         {
  270.             success = FALSE;
  271.  
  272.             if (PIC_Render(pic, PIXFMT_0RGB_32, NULL))
  273.             {
  274.                 ULONG *p = ((ULONG *) pic->array) + sourcex + sourcey * pic->width;
  275.     
  276.                 CreateAlphaArray(p, sourcewidth, sourceheight,
  277.                     RND_SourceWidth, pic->width, RND_AlphaWidth, pic->width,
  278.                     RND_MaskRGB, rgb, TAG_DONE);
  279.     
  280.                 pic->alphapresent = TRUE;
  281.     
  282.                 success = TRUE;    
  283.             }
  284.         }
  285.     }
  286.  
  287.     ReleaseSemaphore(&pic->semaphore);
  288.  
  289.     return success;
  290. }
  291.  
  292.  
  293. /*---------------------------------------------------------------------
  294.  
  295.     insertalpha
  296.  
  297.     fügt eine Zeile Alpha-Channel in einen RGB-Buffer
  298.  
  299. --------------------------------------------------------------------*/
  300.  
  301. struct insertalphadata
  302. {
  303.     UWORD width, totalwidth;
  304.     ULONG *destbuffer;
  305. };
  306.  
  307. #ifdef __MORPHOS__
  308. FUNC_HOOK(ULONG, insertalpha, struct Hook *, hook, APTR, buffer, struct RND_LineMessage *, msg)
  309. #else
  310. ULONG ASM SAVE_DS insertalpha(    register __a0 struct Hook *hook,
  311.                                 register __a2 APTR buffer,
  312.                                 register __a1 struct RND_LineMessage *msg )
  313. #endif
  314. {
  315.     if (msg->RND_LMsg_type == LMSGTYPE_LINE_RENDERED)
  316.     {
  317.         struct insertalphadata *args = (struct insertalphadata *)(hook->h_Data);
  318.  
  319.         InsertAlphaChannel((UBYTE *)buffer, args->width, 1, args->destbuffer, NULL);
  320.         args->destbuffer += args->totalwidth;
  321.     }
  322.  
  323.     return TRUE;
  324. }
  325.  
  326. /*--------------------------------------------------------------------
  327.  
  328.     SetAlpha (pic,array,width,height,tags)
  329.  
  330.     ist array=NULL, so wird der Alphachannel entfernt.
  331.  
  332.     GGFX_DestWidth
  333.     GGFX_DestHeight
  334.  
  335. --------------------------------------------------------------------*/
  336.  
  337. ULONG PIC_SetAlpha(PIC *pic, UBYTE *array, ULONG sourcewidth, ULONG sourceheight, TAGLIST tags)
  338. {
  339.     BOOL success = FALSE;
  340.     UWORD destwidth, destheight, destx, desty;
  341.  
  342.     ObtainSemaphore(&pic->semaphore);
  343.  
  344.     if (array)
  345.     {
  346.         destwidth = GetTagData(GGFX_DestWidth, pic->width, tags);
  347.         destheight = GetTagData(GGFX_DestHeight, pic->height, tags);
  348.         destx = GetTagData(GGFX_DestX, 0, tags);
  349.         desty = GetTagData(GGFX_DestY, 0, tags);
  350.  
  351.         /*
  352.          *    clipping
  353.     
  354.         destwidth = MIN(pic->width - destx, destwidth);
  355.         destheight = MIN(pic->height - desty, destheight);
  356.  
  357.          */
  358.  
  359.         success = TRUE;
  360.  
  361.         if (destwidth && destheight)
  362.         {
  363.             success = FALSE;
  364.  
  365.             FreeRenderVec(pic->alphaarray);
  366.             pic->alphaarray = NULL;
  367.         
  368.             if (PIC_Render(pic, PIXFMT_0RGB_32, NULL))
  369.             {
  370.                 ULONG *dest = ((ULONG *) pic->array) + destx + desty * pic->width;
  371.         
  372.                 if ((destwidth != sourcewidth) || (destheight != sourceheight))
  373.                 {
  374.                     APTR scaleengine;
  375.         
  376.                     if (scaleengine = CreateScaleEngine(sourcewidth, sourceheight,
  377.                         destwidth, destheight, RND_RMHandler, MemHandler, TAG_DONE))
  378.                     {
  379.                         UBYTE *linebuffer;
  380.                         if (linebuffer = AllocRenderVec(MemHandler, destwidth))
  381.                         {
  382.                             struct Hook drawhook;
  383.                             struct insertalphadata args;
  384.         
  385.                             args.width = destwidth;
  386.                             args.totalwidth = pic->width;
  387.                             args.destbuffer = dest;
  388.                             drawhook.h_Data = &args;
  389. #ifdef __MORPHOS__
  390.                             drawhook.h_Entry = (HOOKFUNC) &insertalpha;
  391. #else
  392.                             drawhook.h_Entry = (HOOKFUNC) insertalpha;
  393. #endif
  394.         
  395.                             Scale(scaleengine, array, linebuffer, 
  396.                                 RND_LineHook, &drawhook,
  397.                                 RND_DestWidth, 0, TAG_DONE);
  398.         
  399.                             FreeRenderVec(linebuffer);
  400.         
  401.                             FreeRenderVec(pic->alphaarray);
  402.                             pic->alphaarray = NULL;
  403.                         
  404.                             pic->alphapresent = TRUE;
  405.                             success = TRUE;
  406.                         }
  407.         
  408.                         DeleteScaleEngine(scaleengine);
  409.                     }
  410.                 }
  411.                 else
  412.                 {
  413.                     InsertAlphaChannel(array, sourcewidth, sourceheight, dest,
  414.                         RND_DestWidth, pic->width, TAG_DONE);
  415.                     pic->alphapresent = TRUE;
  416.                     success = TRUE;
  417.                 }
  418.             }
  419.         }
  420.     }
  421.     else
  422.     {
  423.         FreeRenderVec(pic->alphaarray);
  424.         pic->alphaarray = NULL;
  425.         pic->alphapresent = FALSE;
  426.     }
  427.  
  428.     ReleaseSemaphore(&pic->semaphore);
  429.  
  430.     return success;
  431. }
  432.  
  433.  
  434. /*--------------------------------------------------------------------
  435.  
  436.     Crop (pic,x,y,width,height,tags)
  437.  
  438. --------------------------------------------------------------------*/
  439.  
  440. ULONG PIC_Crop(PIC *pic, ULONG x, ULONG y, ULONG width, ULONG height,
  441.     TAGLIST tags)
  442. {
  443.     BOOL success = FALSE;
  444.  
  445.     ObtainSemaphore(&pic->semaphore);
  446.  
  447.     if (PrepareDrawing(pic))
  448.     {
  449.         if (InsertAlphaArray(pic))
  450.         {
  451.             switch (pic->pixelformat)
  452.             {
  453.                 case PIXFMT_0RGB_32:
  454.                 {
  455.                     int i;
  456.                     ULONG *t, *p = ((ULONG *) pic->array) + y*pic->width + x;
  457.                     
  458.                     if (pic->owner)
  459.                     {
  460.                         if(t = AllocRenderVec(MemHandler,width*height*4))
  461.                         {            
  462.                             for(i=0; i<height; ++i)
  463.                             {
  464.                                 TurboCopyMem(p, t+width*i, width*4);
  465.                                 p += pic->width;
  466.                             }
  467.                             FreeRenderVec(pic->array);
  468.                             pic->array = (UBYTE *) t;
  469.                             success = TRUE;
  470.                         }
  471.                     }
  472.                     else
  473.                     {
  474.                         t = (ULONG *) pic->array;
  475.                         for(i=0; i<height; ++i)
  476.                         {
  477.                             TurboCopyMem(p, t+width*i, width*4);
  478.                             p += pic->width;
  479.                         }
  480.                         success = TRUE;
  481.                     }
  482.                     break;
  483.                 }
  484.                         
  485.                 case PIXFMT_CHUNKY_CLUT:
  486.                 {
  487.                     int i;
  488.                     UBYTE *t, *p = ((UBYTE *) pic->array) + y*pic->width + x;
  489.                     
  490.                     if (pic->owner)
  491.                     {
  492.                         if(t = AllocRenderVec(MemHandler,width*height))
  493.                         {            
  494.                             for(i=0; i<height; ++i)
  495.                             {
  496.                                 TurboCopyMem(p, t+width*i, width);
  497.                                 p += pic->width;
  498.                             }
  499.                             FreeRenderVec(pic->array);
  500.                             pic->array = t;
  501.                             success = TRUE;
  502.                         }
  503.                     }
  504.                     else
  505.                     {
  506.                         t = pic->array;
  507.                         for(i=0; i<height; ++i)
  508.                         {
  509.                             TurboCopyMem(p, t+width*i, width);
  510.                             p += pic->width;
  511.                         }
  512.                         success = TRUE;
  513.                     }
  514.                     break;
  515.                 }
  516.             }
  517.         }
  518.     }
  519.  
  520.     if (success)
  521.     {
  522.         pic->width = width;
  523.         pic->height = height;
  524.  
  525.         /*
  526.         if(pic->histogram)
  527.         {
  528.             UnLinkSharedHistogram(pic->histogram);
  529.             pic->histogram = NULL;
  530.         }    
  531.         */
  532.  
  533.     }
  534.  
  535.     ReleaseSemaphore(&pic->semaphore);
  536.  
  537.  
  538.     return success;
  539. }
  540.  
  541.  
  542. /*--------------------------------------------------------------------
  543.  
  544.     Render (pic,pixelformat,tags)
  545.  
  546.     - bei pic->pixelformat = RGB wird auf eine ggf. vorhandene Palette
  547.       gerendert. Wenn keine Palette vorhanden ist, wird eine Palette
  548.       mit 256 Farben erzeugt.
  549.  
  550. --------------------------------------------------------------------*/
  551.  
  552. ULONG PIC_Render(PIC *pic, ULONG pixelformat, TAGLIST tags)
  553. {
  554.     BOOL success = TRUE;
  555.  
  556.     ObtainSemaphore(&pic->semaphore);
  557.  
  558.     if ((pic->pixelformat != pixelformat))
  559.     {
  560.         success = FALSE;
  561.  
  562.         if (pic->directdraw == NULL)
  563.         {
  564.             switch (pic->pixelformat)
  565.             {
  566.                 case PIXFMT_0RGB_32:
  567.     
  568.                     switch (pixelformat)
  569.                     {
  570.                         case PIXFMT_CHUNKY_CLUT:
  571.                         
  572.                             /*
  573.                              *    rgb32 -> chunky
  574.                              */
  575.                         
  576.                             success = TRUE;
  577.             
  578.                             if(!pic->palette)
  579.                             {
  580.                                 success = FALSE;
  581.                                 if (UpdatePicture(pic))
  582.                                 {
  583.                                     if (pic->palette = CreatePalette(RND_RMHandler, MemHandler,
  584.                                         RND_HSType, pic->hstype, TAG_DONE))
  585.                                     {
  586.                                         if (ExtractPalette(pic->histogram->histogram, 
  587.                                             pic->palette, 256, NULL) == EXTP_SUCCESS)
  588.                                         {
  589.                                             success = TRUE;
  590.                                         }
  591.                                     }
  592.                                 }
  593.                             }
  594.     
  595.                             if (success)
  596.                             {
  597.                                 success = ExtractAlphaArray(pic);
  598.                             }
  599.             
  600.                             if (success)
  601.                             {
  602.                                 success = FALSE;
  603.                                 if(pic->owner)
  604.                                 {
  605.                                     UBYTE *t;
  606.                                     
  607.                                     if (t = AllocRenderVec(MemHandler, pic->width*pic->height))
  608.                                     {
  609.                                         if (Render((APTR)pic->array, pic->width, pic->height, 
  610.                                             t, pic->palette, NULL) == REND_SUCCESS)
  611.                                         {
  612.                                             success = TRUE;
  613.                                             pic->directdraw = NULL;        //!!
  614.                                             FreeRenderVec(pic->array);
  615.                                             pic->array = t;
  616.                                         }
  617.                                         else
  618.                                         {
  619.                                             FreeRenderVec(t);
  620.                                         }
  621.                                     }
  622.                                 }
  623.                                 else
  624.                                 {
  625.                                     if (Render((APTR)pic->array, pic->width, pic->height, pic->array,
  626.                                         pic->palette, NULL) == REND_SUCCESS)
  627.                                     {
  628.                                         pic->directdraw = NULL;        //!!
  629.                                         success = TRUE;
  630.                                     }
  631.                                 }
  632.                             }
  633.                             
  634.                             if (!success)
  635.                             {
  636.                                 if (pic->palette)
  637.                                 {
  638.                                     DeletePalette(pic->palette);
  639.                                     pic->palette = NULL;
  640.                                 }                
  641.                             }
  642.                             break;
  643.     
  644.                         case PIXFMT_RGB_24:
  645.                         
  646.                             /*
  647.                              *    rgb32->rgb24
  648.                              */
  649.                     
  650.                             success = ExtractAlphaArray(pic);
  651.                             
  652.                             if (success)
  653.                             {
  654.                                 ULONG i;
  655.                                 UBYTE *p24 = pic->array;
  656.                                 UBYTE *p32 = pic->array;
  657.                                 
  658.                                 for(i = 0; i < pic->width * pic->height; ++i)
  659.                                 {
  660.                                     *p24++ = p32[1];
  661.                                     *p24++ = p32[2];
  662.                                     *p24++ = p32[3];
  663.                                     p32 += 4;
  664.                                 }    
  665.                             }
  666.     
  667.                             break;
  668.                     }
  669.                     break;
  670.     
  671.                 case PIXFMT_CHUNKY_CLUT:
  672.     
  673.                     switch (pixelformat)
  674.                     {
  675.                         case PIXFMT_0RGB_32:
  676.     
  677.                             /*
  678.                              *    chunky -> rgb32
  679.                              */
  680.     
  681.                             if (pic->owner)
  682.                             {
  683.                                 ULONG *t;
  684.                                 if(t = AllocRenderVec(MemHandler, pic->width*pic->height*4))
  685.                                 {
  686.                                     Chunky2RGB(pic->array,pic->width,pic->height,t,pic->palette,NULL);
  687.                                     
  688.                                     FreeRenderVec(pic->array);
  689.                                     DeletePalette(pic->palette);
  690.                                     pic->palette = NULL;
  691.                                     pic->array = (UBYTE *) t;
  692.                                     pic->directdraw = NULL;        //!!
  693.                                     success = TRUE;
  694.                                 }
  695.                             }
  696.                             else
  697.                             {
  698.                                 if(pic->width*pic->height*4 <= pic->maxbytes)
  699.                                 {
  700.                                     ULONG *t;
  701.                                     if(t = AllocRenderVec(MemHandler, pic->width*pic->height*4))
  702.                                     {
  703.                                         Chunky2RGB(pic->array,pic->width,pic->height,t,pic->palette,NULL);
  704.                                         TurboCopyMem(t, pic->array, pic->width*pic->height*4);
  705.                                         FreeRenderVec(t);
  706.                                         DeletePalette(pic->palette);
  707.                                         pic->palette = NULL;
  708.                                         pic->directdraw = NULL;        //!!
  709.                                         success = TRUE;
  710.                                     }
  711.                                 }
  712.                             }
  713.                             
  714.                             if (success)
  715.                             {
  716.                                 pic->pixelformat = pixelformat;     /* wichtig! */
  717.                                 success = InsertAlphaArray(pic);
  718.                             }
  719.                             
  720.                             break;
  721.     
  722.                         case PIXFMT_RGB_24:
  723.                         
  724.                             /*
  725.                              *    chunky->rgb24
  726.                              */
  727.     
  728.                             if (PIC_Render(pic, PIXFMT_0RGB_32, tags))
  729.                             {
  730.                                 if (PIC_Render(pic, PIXFMT_RGB_24, tags))
  731.                                 {
  732.                                     success = TRUE;
  733.                                 }
  734.                             }
  735.                             break;
  736.                     }
  737.                     break;
  738.     
  739.                 case PIXFMT_RGB_24:
  740.                     switch (pixelformat)
  741.                     {
  742.                         case PIXFMT_0RGB_32:
  743.                         {
  744.                             /*
  745.                              *    RGB24 -> RGB32
  746.                              */
  747.     
  748.                             ULONG i;
  749.                             UBYTE *p24, *p32;
  750.                             
  751.                             if (pic->width * pic->height * 4 <= pic->maxbytes)
  752.                             {
  753.                                 p24 = pic->array + pic->width * pic->height * 3;
  754.                                 p32 = pic->array + pic->width * pic->height * 4;
  755.                                 for(i = 0; i < pic->width * pic->height; ++i)
  756.                                 {
  757.                                     p32 -= 4;
  758.                                     p32[3] = *--p24;
  759.                                     p32[2] = *--p24;
  760.                                     p32[1] = *--p24;
  761.                                     p32[0] = 0;
  762.                                 }
  763.                                 success = TRUE;
  764.                             }
  765.                             else
  766.                             {
  767.                                 success = FALSE;
  768.                                 if (pic->owner)
  769.                                 {
  770.                                     if (p32 = AllocRenderVecClear(MemHandler, pic->width * pic->height * 4))
  771.                                     {
  772.                                         UBYTE *newarray = p32;
  773.                                         p24 = pic->array;
  774.                                         for(i = 0; i < pic->width * pic->height; ++i)
  775.                                         {
  776.                                             p32[1] = *p24++;
  777.                                             p32[2] = *p24++;
  778.                                             p32[3] = *p24++;
  779.                                             p32 += 4;
  780.                                         }
  781.                                         FreeRenderVec(pic->array);
  782.                                         pic->array = newarray;
  783.                                         success = TRUE;
  784.                                     }
  785.                                 }
  786.                             }
  787.                             
  788.                             if (success)
  789.                             {
  790.                                 pic->pixelformat = pixelformat;     /* wichtig! */
  791.                                 success = InsertAlphaArray(pic);
  792.                             }
  793.                             break;
  794.                         }
  795.     
  796.                         case PIXFMT_CHUNKY_CLUT:
  797.                         
  798.                             /*
  799.                              *    rgb24->chunky
  800.                              */
  801.                             
  802.                             if (PIC_Render(pic, PIXFMT_0RGB_32, tags))
  803.                             {
  804.                                 if (PIC_Render(pic, PIXFMT_CHUNKY_CLUT, tags))
  805.                                 {
  806.                                     success = TRUE;
  807.                                 }
  808.                             }
  809.                             break;
  810.                     }
  811.                     break;
  812.             }
  813.         }
  814.  
  815.         if (success)
  816.         {
  817.             pic->pixelformat = pixelformat;
  818.             
  819.             /*
  820.             if(pic->histogram)
  821.             {
  822.                 UnLinkSharedHistogram(pic->histogram);
  823.                 pic->histogram = NULL;
  824.             }
  825.             */
  826.         }
  827.     }
  828.  
  829.  
  830.     ReleaseSemaphore(&pic->semaphore);
  831.  
  832.     return success;
  833. }
  834.  
  835.  
  836. /*--------------------------------------------------------------------
  837.  
  838.     Scale (width,height,tags)
  839.  
  840. --------------------------------------------------------------------*/
  841.  
  842. ULONG PIC_Scale(PIC *pic, ULONG width, ULONG height,
  843.     TAGLIST tags)
  844. {
  845.     BOOL success = TRUE;
  846.  
  847.     ObtainSemaphore(&pic->semaphore);
  848.  
  849.     if ((pic->width != width) || (pic->height != height))
  850.     {
  851.         if (success = PrepareDrawing(pic))
  852.         {
  853.             if (success = InsertAlphaArray(pic))
  854.             {
  855.                 APTR scaleengine;
  856.                 success = FALSE;
  857.             
  858.                 if (scaleengine = CreateScaleEngine(pic->width, pic->height, width, height,
  859.                     RND_PixelFormat, pic->pixelformat,
  860.                     RND_RMHandler, MemHandler, TAG_DONE))
  861.                 {
  862.                     if (pic->owner)
  863.                     {
  864.                         APTR t;
  865.                         if (t = AllocRenderVec(MemHandler, 
  866.                             width*height*PIXELSIZE(pic->pixelformat)))
  867.                         {
  868.                             Scale(scaleengine, pic->array, t, NULL);
  869.                             FreeRenderVec(pic->array);
  870.                             pic->array = t;
  871.                             success = TRUE;
  872.                         }
  873.                     }
  874.                     else
  875.                     {
  876.                         if (width*height*PIXELSIZE(pic->pixelformat) <= pic->maxbytes)
  877.                         {
  878.                             if(width <= pic->width)
  879.                             {
  880.                                 Scale(scaleengine, pic->array, pic->array, NULL);
  881.                                 success = TRUE;
  882.                             }
  883.                             else
  884.                             {
  885.                                 APTR t;
  886.                                 if (t = AllocRenderVec(MemHandler,
  887.                                     width*height*PIXELSIZE(pic->pixelformat)))
  888.                                 {
  889.                                     Scale(scaleengine, pic->array, t, NULL);
  890.                                     TurboCopyMem(t, pic->array, width*height*PIXELSIZE(pic->pixelformat));
  891.                                     FreeRenderVec(t);
  892.                                     success = TRUE;
  893.                                 }                    
  894.                             }
  895.                         }
  896.                     }
  897.                     DeleteScaleEngine(scaleengine);
  898.                 }
  899.             }
  900.         }
  901.     }
  902.  
  903.     if (success)
  904.     {
  905.         pic->width = width;
  906.         pic->height = height;
  907.  
  908.         /*
  909.         if(pic->histogram)
  910.         {
  911.             UnLinkSharedHistogram(pic->histogram);
  912.             pic->histogram = NULL;
  913.         }
  914.         */    
  915.     }
  916.  
  917.     ReleaseSemaphore(&pic->semaphore);
  918.  
  919.     return success;
  920. }
  921.  
  922.  
  923.  
  924. /*---------------------------------------------------------------------
  925.  
  926.     mixrgb
  927.  
  928.     mixt eine Zeile RGB auf einen RGB-Buffer
  929.  
  930. --------------------------------------------------------------------*/
  931.  
  932. struct mixrgbdata
  933. {
  934.     UWORD width, ratio;
  935.     ULONG *destbuffer;
  936.     UWORD totalwidth;
  937. };
  938.  
  939. #ifdef __MORPHOS__
  940. FUNC_HOOK(ULONG, mixrgb, struct Hook *, hook, APTR, buffer, struct RND_LineMessage *, msg)
  941. #else
  942. ULONG ASM SAVE_DS mixrgb(    register __a0 struct Hook *hook,
  943.                             register __a2 APTR buffer,
  944.                             register __a1 struct RND_LineMessage *msg )
  945. #endif
  946. {
  947.     if (msg->RND_LMsg_type == LMSGTYPE_LINE_RENDERED)
  948.     {
  949.         struct mixrgbdata *args = (struct mixrgbdata *)(hook->h_Data);
  950.  
  951.         MixRGBArray((ULONG *)buffer, args->width, 1, args->destbuffer, args->ratio, NULL);
  952.  
  953.         args->destbuffer += args->totalwidth;
  954.     }
  955.  
  956.     return TRUE;
  957. }
  958.  
  959.  
  960. /*---------------------------------------------------------------------
  961.  
  962.     mixchunkyrgb
  963.  
  964.     mixt eine Zeile Chunky auf einen RGB-Buffer
  965.  
  966. --------------------------------------------------------------------*/
  967.  
  968. struct mixchunkyrgbdata
  969. {
  970.     UWORD width, ratio;
  971.     ULONG *destbuffer;
  972.     ULONG *rgblinebuffer;
  973.     APTR palette;
  974.     UWORD totalwidth;
  975. };
  976.         
  977. #ifdef __MORPHOS__
  978. FUNC_HOOK(ULONG, mixchunkyrgb, struct Hook *, hook, APTR, buffer, struct RND_LineMessage *, msg)
  979. #else
  980. ULONG ASM SAVE_DS mixchunkyrgb(    register __a0 struct Hook *hook,
  981.                                 register __a2 APTR buffer,
  982.                                 register __a1 struct RND_LineMessage *msg )
  983. #endif
  984. {
  985.     if (msg->RND_LMsg_type == LMSGTYPE_LINE_RENDERED)
  986.     {
  987.         struct mixchunkyrgbdata *args = (struct mixchunkyrgbdata *) (hook->h_Data);
  988.  
  989.         Chunky2RGB(buffer, args->width, 1, args->rgblinebuffer, args->palette, NULL);
  990.         MixRGBArray(args->rgblinebuffer, args->width, 1, args->destbuffer, args->ratio, NULL);
  991.  
  992.         args->destbuffer += args->totalwidth;
  993.     }
  994.  
  995.     return TRUE;
  996. }
  997.  
  998.  
  999. /*--------------------------------------------------------------------
  1000.  
  1001.     Mix (pic1,pic2,tags)
  1002.  
  1003.     - es wird pic1 + pic2 -> pic1 gemischt, also das Fremdbild
  1004.       auf das Bild gemischt, auf das die Methode angewandt wird.
  1005.  
  1006.     - das Fremdbild wird temporär umgerechnet und skaliert,
  1007.       falls erforderlich.
  1008.  
  1009.     Tags:
  1010.         GGFX_Ratio (0-255)    Default: 128
  1011.  
  1012. --------------------------------------------------------------------*/
  1013.  
  1014. ULONG PIC_Mix(PIC *pic, PIC *mixpic, TAGLIST tags)
  1015. {
  1016.     BOOL success = TRUE;
  1017.  
  1018.     UWORD destwidth, destheight, destx, desty;
  1019.     UWORD sourcewidth, sourceheight, sourcex, sourcey;
  1020.  
  1021.     ObtainSemaphore(&pic->semaphore);
  1022.  
  1023.     destwidth = GetTagData(GGFX_DestWidth, pic->width, tags);
  1024.     destheight = GetTagData(GGFX_DestHeight, pic->height, tags);
  1025.     destx = GetTagData(GGFX_DestX, 0, tags);
  1026.     desty = GetTagData(GGFX_DestY, 0, tags);
  1027.     
  1028.     sourcewidth = GetTagData(GGFX_SourceWidth, mixpic->width, tags);
  1029.     sourceheight = GetTagData(GGFX_SourceHeight, mixpic->height, tags);
  1030.     sourcex = GetTagData(GGFX_SourceX, 0, tags);
  1031.     sourcey = GetTagData(GGFX_SourceY, 0, tags);
  1032.     
  1033.  
  1034.     /*
  1035.      *    clipping
  1036.  
  1037.     sourcewidth = MIN(mixpic->width - sourcex, sourcewidth);
  1038.     sourceheight = MIN(mixpic->height - sourcey, sourceheight);
  1039.     destwidth = MIN(pic->width - destx, destwidth);
  1040.     destheight = MIN(pic->height - desty, destheight);
  1041.  
  1042.      */
  1043.  
  1044.  
  1045.     if (sourcewidth && sourceheight && destwidth && destheight)
  1046.     {
  1047.         success = FALSE;
  1048.     
  1049.         if (PIC_Render(pic, PIXFMT_0RGB_32, NULL))
  1050.         {
  1051.             APTR scaleengine = NULL;
  1052.             success = TRUE;
  1053.         
  1054.             ObtainSemaphoreShared(&mixpic->semaphore);
  1055.         
  1056.             if ((sourcewidth != destwidth) || (sourceheight != destheight))
  1057.             {
  1058.                 success = FALSE;
  1059.                 if (scaleengine = CreateScaleEngine(sourcewidth, sourceheight,
  1060.                     destwidth, destheight, RND_PixelFormat, mixpic->pixelformat,
  1061.                     RND_RMHandler, MemHandler, TAG_DONE))
  1062.                 {
  1063.                     success = TRUE;
  1064.                 }        
  1065.             }            
  1066.         
  1067.             if (success)
  1068.             {
  1069.                 ULONG *dest = ((ULONG *) pic->array) + destx + desty * pic->width;
  1070.                 success = FALSE;
  1071.         
  1072.                 switch (mixpic->pixelformat)
  1073.                 {
  1074.                     case PIXFMT_0RGB_32:
  1075.                     {
  1076.                         ULONG *source = ((ULONG *) mixpic->array) + sourcex + sourcey * mixpic->width;
  1077.                         if (scaleengine)
  1078.                         {
  1079.                             APTR linebuffer;
  1080.                 
  1081.                             if (linebuffer = AllocRenderVec(MemHandler, destwidth*4))
  1082.                             {
  1083.                                 struct Hook drawhook;
  1084.                                 struct mixrgbdata args;
  1085.         
  1086.                                 args.width = destwidth;
  1087.                                 args.totalwidth = pic->width;
  1088.                                 args.ratio = GetTagData(GGFX_Ratio, 128, tags);
  1089.                                 args.destbuffer = dest;
  1090.                                 drawhook.h_Data = &args;
  1091. #ifdef __MORPHOS__
  1092.                                 drawhook.h_Entry = (HOOKFUNC) &mixrgb;
  1093. #else
  1094.                                 drawhook.h_Entry = (HOOKFUNC) mixrgb;
  1095. #endif
  1096.         
  1097.                                 Scale(scaleengine, source, 
  1098.                                     linebuffer, RND_SourceWidth, mixpic->width,
  1099.                                     RND_LineHook, &drawhook, RND_DestWidth, 0, TAG_DONE);
  1100.         
  1101.                                 FreeRenderVec(linebuffer);
  1102.         
  1103.                                 success = TRUE;
  1104.                             }
  1105.                         }
  1106.                         else
  1107.                         {
  1108.                             MixRGBArray(source, sourcewidth, sourceheight, dest,
  1109.                                 GetTagData(GGFX_Ratio, 128, tags), 
  1110.                                 RND_SourceWidth, mixpic->width,
  1111.                                 RND_DestWidth, pic->width, NULL);
  1112.                         }
  1113.                         break;
  1114.         
  1115.                     }                
  1116.                     case PIXFMT_CHUNKY_CLUT:
  1117.                     {
  1118.                         UBYTE *source = ((UBYTE *) mixpic->array) + sourcex + sourcey * mixpic->width;
  1119.         
  1120.                         if (scaleengine)
  1121.                         {
  1122.                             UBYTE *buffer;
  1123.                 
  1124.                             if (buffer = AllocRenderVec(MemHandler, destwidth*5))
  1125.                             {
  1126.                                 struct Hook drawhook;
  1127.                                 struct mixchunkyrgbdata args;
  1128.         
  1129.                                 args.width = destwidth;
  1130.                                 args.totalwidth = pic->width;
  1131.                                 args.ratio = GetTagData(GGFX_Ratio, 128, tags);
  1132.                                 args.destbuffer = dest;
  1133.                                 args.palette = mixpic->palette;
  1134.                                 args.rgblinebuffer = (ULONG *)buffer;
  1135.                                 drawhook.h_Data = &args;
  1136. #ifdef __MORPHOS__
  1137.                                 drawhook.h_Entry = (HOOKFUNC) &mixchunkyrgb;
  1138. #else
  1139.                                 drawhook.h_Entry = (HOOKFUNC) mixchunkyrgb;
  1140. #endif
  1141.         
  1142.                                 Scale(scaleengine, source, buffer+destwidth*4,
  1143.                                     RND_LineHook, &drawhook, RND_DestWidth, 0,
  1144.                                     RND_SourceWidth, mixpic->width, TAG_DONE);
  1145.         
  1146.                                 FreeRenderVec(buffer);
  1147.         
  1148.                                 success = TRUE;
  1149.                             }
  1150.                         }
  1151.                         else
  1152.                         {
  1153.                             APTR buffer;
  1154.                             if (buffer = AllocRenderVec(MemHandler, destwidth*4))
  1155.                             {
  1156.                                 struct Hook drawhook;
  1157.                                 struct mixrgbdata args;
  1158.         
  1159.                                 args.width = sourcewidth;
  1160.                                 args.totalwidth = pic->width;
  1161.                                 args.ratio = GetTagData(GGFX_Ratio, 128, tags);
  1162.                                 args.destbuffer = dest;
  1163.                                 drawhook.h_Data = &args;
  1164. #ifdef __MORPHOS__
  1165.                                 drawhook.h_Entry = (HOOKFUNC) &mixrgb;
  1166. #else
  1167.                                 drawhook.h_Entry = (HOOKFUNC) mixrgb;
  1168. #endif
  1169.         
  1170.                                 Chunky2RGB(source, sourcewidth, sourceheight, buffer,
  1171.                                     mixpic->palette, RND_DestWidth, 0,
  1172.                                     RND_SourceWidth, mixpic->width,
  1173.                                     RND_LineHook, &drawhook, TAG_DONE);
  1174.                                 FreeRenderVec(buffer);
  1175.                                 
  1176.                                 success = TRUE;
  1177.                             }
  1178.                         }
  1179.                         break;
  1180.                     }
  1181.                 }
  1182.             }
  1183.         
  1184.             ReleaseSemaphore(&mixpic->semaphore);
  1185.         
  1186.             if (scaleengine)
  1187.             {
  1188.                 DeleteScaleEngine(scaleengine);
  1189.             }
  1190.         }
  1191.     }
  1192.     
  1193.     ReleaseSemaphore(&pic->semaphore);
  1194.  
  1195.     return success;
  1196. }
  1197.  
  1198.  
  1199.  
  1200.  
  1201. /*--------------------------------------------------------------------
  1202.  
  1203.     TintAlpha (pic1, RGB, tags)
  1204.  
  1205.     Tags:
  1206.         GGFX_DestWidth
  1207.         GGFX_DestHeight
  1208.         GGFX_DestX
  1209.         GGFX_DestY
  1210.  
  1211. --------------------------------------------------------------------*/
  1212.  
  1213. ULONG PIC_TintAlpha(PIC *pic, ULONG rgb, TAGLIST tags)
  1214. {
  1215.     BOOL success = FALSE;
  1216.  
  1217.     UWORD destwidth, destheight, destx, desty;
  1218.  
  1219.     ObtainSemaphore(&pic->semaphore);
  1220.  
  1221.     destwidth = GetTagData(GGFX_DestWidth, pic->width, tags);
  1222.     destheight = GetTagData(GGFX_DestHeight, pic->height, tags);
  1223.     destx = GetTagData(GGFX_DestX, 0, tags);
  1224.     desty = GetTagData(GGFX_DestY, 0, tags);
  1225.  
  1226.     if (destwidth && destheight)
  1227.     {
  1228.         if (PrepareDrawing(pic))
  1229.         {
  1230.             if (InsertAlphaArray(pic))
  1231.             {
  1232.                 ULONG *dest = ((ULONG *) pic->array) + destx + desty * pic->width;
  1233.                 ULONG *mixline;
  1234.                 
  1235.                 if (mixline = AllocRenderVec(MemHandler, destwidth*4))
  1236.                 {
  1237.                     int i;
  1238.                     for (i = 0; i < destwidth; ++i)
  1239.                     {
  1240.                         mixline[i] = rgb;
  1241.                     }
  1242.             
  1243.                     ApplyAlphaChannel(mixline, destwidth, destheight, dest,
  1244.                         RND_SourceWidth, 0,
  1245.                         RND_DestWidth, pic->width,
  1246.                         RND_AlphaChannel, dest,
  1247.                         RND_AlphaWidth, pic->width,
  1248.                         TAG_DONE);
  1249.                 
  1250.  
  1251.                     FreeRenderVec(mixline);
  1252.  
  1253.                     success = TRUE;
  1254.                 }
  1255.             }
  1256.         }
  1257.     }
  1258.  
  1259.     
  1260.     ReleaseSemaphore(&pic->semaphore);
  1261.  
  1262.     return success;
  1263. }
  1264.  
  1265.  
  1266.  
  1267. /*--------------------------------------------------------------------
  1268.  
  1269.     Tint (pic1,RGB,tags)
  1270.  
  1271.     Tags:
  1272.         GGFX_Ratio (0-255)    Default: 128
  1273.         GGFX_DestWidth
  1274.         GGFX_DestHeight
  1275.         GGFX_DestX
  1276.         GGFX_DestY
  1277.  
  1278. --------------------------------------------------------------------*/
  1279.  
  1280. ULONG PIC_Tint(PIC *pic, ULONG rgb, TAGLIST tags)
  1281. {
  1282.     BOOL success = TRUE;
  1283.  
  1284.     UWORD destwidth, destheight, destx, desty;
  1285.  
  1286.     ObtainSemaphore(&pic->semaphore);
  1287.  
  1288.     destwidth = GetTagData(GGFX_DestWidth, pic->width, tags);
  1289.     destheight = GetTagData(GGFX_DestHeight, pic->height, tags);
  1290.     destx = GetTagData(GGFX_DestX, 0, tags);
  1291.     desty = GetTagData(GGFX_DestY, 0, tags);
  1292.  
  1293.     if (destwidth && destheight)
  1294.     {
  1295.         success = FALSE;
  1296.         
  1297.         if (PIC_Render(pic, PIXFMT_0RGB_32, NULL))
  1298.         {
  1299.             ULONG *dest = ((ULONG *) pic->array) + destx + desty * pic->width;
  1300.         
  1301.             TintRGBArray(dest, destwidth, destheight, rgb,
  1302.                 GetTagData(GGFX_Ratio, 128, tags), dest,
  1303.                 RND_SourceWidth, pic->width,
  1304.                 RND_DestWidth, pic->width, TAG_DONE);
  1305.     
  1306.             success = TRUE;
  1307.         }
  1308.     }
  1309.  
  1310.     
  1311.     ReleaseSemaphore(&pic->semaphore);
  1312.  
  1313.     return success;
  1314. }
  1315.  
  1316.  
  1317.  
  1318. /*---------------------------------------------------------------------
  1319.  
  1320.     mixrgbalpha
  1321.  
  1322.     mixt eine Zeile RGB auf einen RGB-Buffer mit Alpha-Channel
  1323.  
  1324. --------------------------------------------------------------------*/
  1325.  
  1326. struct mixalphadata
  1327. {
  1328.     UWORD width, ratio;
  1329.     ULONG *destbuffer;
  1330.     UWORD totalwidth_dest;
  1331.     BOOL alphachannel_source;
  1332.     BOOL alphachannel_dest;
  1333. };
  1334.  
  1335. #ifdef __MORPHOS__
  1336. FUNC_HOOK(ULONG, mixrgbalpha, struct Hook *, hook, APTR, buffer, struct RND_LineMessage *, msg)
  1337. #else
  1338. ULONG ASM SAVE_DS mixrgbalpha(    register __a0 struct Hook *hook,
  1339.                                 register __a2 APTR buffer,
  1340.                                 register __a1 struct RND_LineMessage *msg )
  1341. #endif
  1342. {
  1343.     if (msg->RND_LMsg_type == LMSGTYPE_LINE_RENDERED)
  1344.     {
  1345.         struct mixalphadata *args = (struct mixalphadata *)(hook->h_Data);
  1346.  
  1347.         MixAlphaChannel((ULONG *) buffer, args->destbuffer, args->width, 1,    args->destbuffer,
  1348.                 RND_AlphaChannel, args->alphachannel_source ? (ULONG) buffer : NULL,
  1349.                 RND_AlphaChannel2, args->alphachannel_dest ? (ULONG) args->destbuffer : NULL,
  1350.                 TAG_DONE);
  1351.  
  1352.         args->destbuffer += args->totalwidth_dest;
  1353.     }
  1354.  
  1355.     return TRUE;
  1356. }
  1357.  
  1358.  
  1359. /*--------------------------------------------------------------------
  1360.  
  1361.     MixAlpha (pic1,pic2,tags)
  1362.  
  1363.     - es wird pic1 + pic2 -> pic1 gemischt, also das Fremdbild
  1364.       auf das Bild gemischt, auf das die Methode angewandt wird.
  1365.  
  1366.     - es werden alle etwaigen Alpha-Channels berücksichtigt. Ist
  1367.       gar kein Alpha-Channel vorhanden, wird 50:50 gemischt.
  1368.  
  1369.     GGFX_DestWidth    Zielbreite im aktuellen Bild
  1370.     GGFX_DestHeight    Zielhöhe im aktuellen Bild
  1371.     GGFX_DestX        Ziel-X im aktuellen Bild
  1372.     GGFX_DestY        Ziel-Y im aktuellen Bild
  1373.  
  1374.     GGFX_SourceWidth    Breite im zweiten Bild
  1375.     GGFX_SourceHeight    Höhe im zweiten Bild
  1376.     GGFX_SourceX        Ursprung-X im zweiten Bild
  1377.     GGFX_SourceY        Ursprung-Y im zweiten Bild
  1378.  
  1379. --------------------------------------------------------------------*/
  1380.  
  1381. ULONG PIC_MixAlpha(PIC *pic, PIC *mixpic, TAGLIST tags)
  1382. {
  1383.     BOOL success = FALSE;
  1384.  
  1385.     ObtainSemaphore(&pic->semaphore);
  1386.  
  1387.     if (InsertAlphaArray(pic))
  1388.     {
  1389.         ObtainSemaphore(&mixpic->semaphore);
  1390.  
  1391.         if (InsertAlphaArray(mixpic))
  1392.         {
  1393.             if (PIC_Render(pic, PIXFMT_0RGB_32, NULL))
  1394.             {
  1395.                 if (PIC_Render(mixpic, PIXFMT_0RGB_32, NULL))
  1396.                 {
  1397.                     UWORD sourcewidth, sourceheight, sourcex, sourcey;
  1398.                     UWORD destwidth, destheight, destx, desty;
  1399.                     APTR scaleengine = NULL;
  1400.         
  1401.                     destwidth = GetTagData(GGFX_DestWidth, pic->width, tags);
  1402.                     destheight = GetTagData(GGFX_DestHeight, pic->height, tags);
  1403.                     destx = GetTagData(GGFX_DestX, 0, tags);
  1404.                     desty = GetTagData(GGFX_DestY, 0, tags);
  1405.  
  1406.                     sourcewidth = GetTagData(GGFX_SourceWidth, mixpic->width, tags);
  1407.                     sourceheight = GetTagData(GGFX_SourceHeight, mixpic->height, tags);
  1408.                     sourcex = GetTagData(GGFX_SourceX, 0, tags);
  1409.                     sourcey = GetTagData(GGFX_SourceY, 0, tags);
  1410.  
  1411.  
  1412.                     /*
  1413.                      *    clipping
  1414.             
  1415.                     sourcewidth = MIN(mixpic->width - sourcex, sourcewidth);
  1416.                     sourceheight = MIN(mixpic->height - sourcey, sourceheight);
  1417.                     destwidth = MIN(pic->width - destx, destwidth);
  1418.                     destheight = MIN(pic->height - desty, destheight);
  1419.  
  1420.                      */
  1421.  
  1422.                     success = TRUE;
  1423.             
  1424.                     if (sourcewidth && sourceheight && destwidth && destheight)
  1425.                     {
  1426.                         if ((destwidth != sourcewidth) || (destheight != sourceheight))
  1427.                         {
  1428.                             success = FALSE;
  1429.                             if (scaleengine = CreateScaleEngine(sourcewidth, sourceheight,
  1430.                                 destwidth, destheight,
  1431.                                 RND_PixelFormat, PIXFMT_0RGB_32,
  1432.                                 RND_RMHandler, MemHandler, TAG_DONE))
  1433.                             {
  1434.                                 success = TRUE;
  1435.                             }        
  1436.                         }            
  1437.                 
  1438.                         if (success)
  1439.                         {
  1440.                             ULONG *source = ((ULONG *) mixpic->array) + sourcex + sourcey * mixpic->width;
  1441.                             ULONG *dest = ((ULONG *) pic->array) + destx + desty * pic->width;
  1442.                             success = FALSE;
  1443.                 
  1444.                             if (scaleengine)
  1445.                             {
  1446.                                 APTR linebuffer;
  1447.                             
  1448.                                 if (linebuffer = AllocRenderVec(MemHandler, destwidth*4))
  1449.                                 {
  1450.                                     struct Hook drawhook;
  1451.                                     struct mixalphadata args;
  1452.                 
  1453.                                     args.width = destwidth;
  1454.                                     args.totalwidth_dest = pic->width;
  1455.                                     args.destbuffer = dest;
  1456.                                     args.alphachannel_source = mixpic->alphapresent;
  1457.                                     args.alphachannel_dest = pic->alphapresent;
  1458.                                     drawhook.h_Data = &args;
  1459. #ifdef __MORPHOS__
  1460.                                     drawhook.h_Entry = (HOOKFUNC) &mixrgbalpha;
  1461. #else
  1462.                                     drawhook.h_Entry = (HOOKFUNC) mixrgbalpha;
  1463. #endif
  1464.                 
  1465.                                     Scale(scaleengine, (APTR) source, linebuffer,
  1466.                                         RND_LineHook, &drawhook, RND_SourceWidth, mixpic->width,
  1467.                                         RND_DestWidth, 0, TAG_DONE);
  1468.                 
  1469.                                     FreeRenderVec(linebuffer);
  1470.                 
  1471.                                     success = TRUE;
  1472.                                 }
  1473.                             }
  1474.                             else
  1475.                             {
  1476.                                 MixAlphaChannel(source, dest, destwidth, destheight, dest,
  1477.                                     RND_SourceWidth, mixpic->width,
  1478.                                     RND_SourceWidth2, pic->width,
  1479.                                     RND_DestWidth, pic->width,
  1480.                                     RND_AlphaChannel, mixpic->alphapresent ? (APTR) source : NULL,
  1481.                                     RND_AlphaChannel2, pic->alphapresent ? (APTR) dest : NULL,
  1482.                                     RND_AlphaWidth, mixpic->width,
  1483.                                     RND_AlphaWidth2, pic->width,
  1484.                                     TAG_DONE);
  1485.                             }
  1486.                         }
  1487.                 
  1488.                         if (scaleengine)
  1489.                         {
  1490.                             DeleteScaleEngine(scaleengine);
  1491.                         }
  1492.                     }
  1493.                 }
  1494.             }
  1495.         }
  1496.         ReleaseSemaphore(&mixpic->semaphore);
  1497.     }
  1498.  
  1499.     ReleaseSemaphore(&pic->semaphore);
  1500.  
  1501.     return success;
  1502. }
  1503.  
  1504.  
  1505. /*--------------------------------------------------------------------
  1506.  
  1507.     MapDrawHandle (pic, drawhandle, tags)
  1508.  
  1509.     mappt ein Bild auf ein Drawhandle, das heißt, Format
  1510.     und Farben werden angepaßt. Damit kann ein Bild sehr schnell
  1511.     in den entsprechenden Drawhandle gezeichnet werden.
  1512.  
  1513. --------------------------------------------------------------------*/
  1514.  
  1515. ULONG PIC_MapDrawHandle(PIC *pic, struct DrawHandle *dh,
  1516.     TAGLIST tags)
  1517. {
  1518.     BOOL success = FALSE;
  1519.  
  1520.     ObtainSemaphore(&pic->semaphore);
  1521.  
  1522.     if (dh)
  1523.     {
  1524.         if (dh->rasthandle->truecolor)
  1525.         {
  1526.             success = PIC_Render(pic, PIXFMT_0RGB_32, NULL);
  1527.         }
  1528.         else
  1529.         {
  1530.             #ifndef NDEBUG
  1531.             if (!(dh->realpalette && dh->mainpentab))
  1532.             {
  1533.                 DB(kprintf("*** MapDrawHandle Panic!!!\n"));
  1534.             }
  1535.             else
  1536.             {
  1537.             #endif
  1538.         
  1539.             success = PIC_RenderPalette(pic, dh->realpalette, 
  1540.                     GGFX_PaletteFormat, PALFMT_PALETTE,
  1541.                     GGFX_PenTable, dh->mainpentab, TAG_DONE);
  1542.  
  1543.             #ifndef NDEBUG
  1544.             }
  1545.             #endif
  1546.         }
  1547.     }
  1548.  
  1549.  
  1550.     if (success)
  1551.     {
  1552.         pic->directdraw = dh;
  1553.     }
  1554.  
  1555.  
  1556.     ReleaseSemaphore(&pic->semaphore);
  1557.  
  1558.     return success;
  1559. }
  1560.  
  1561.  
  1562. /*--------------------------------------------------------------------
  1563.  
  1564.     RenderPalette (pic, palette, tags)
  1565.  
  1566.     rendert ein Picture auf PIXFMT_CHUNKY_CLUT mit angegebener
  1567.     Palette und Pentab und setzt die Palette. pentab darf NULL sein,
  1568.     palette nicht.
  1569.  
  1570.     GGFX_PenTable
  1571.     GGFX_PaletteFormat
  1572.     GGFX_NumColors
  1573.  
  1574. --------------------------------------------------------------------*/
  1575.  
  1576. #ifndef __MORPHOS__
  1577. ULONG PIC_RenderPalette(PIC *pic, APTR palette, Tag tag1, ...)
  1578. {
  1579.     return PIC_RenderPaletteA(pic, palette, (TAGLIST) &tag1);    
  1580. }
  1581. #endif
  1582.  
  1583. ULONG PIC_RenderPaletteA(PIC *pic, APTR palette, TAGLIST tags)
  1584. {
  1585.     UBYTE *pentab;
  1586.     BOOL success = FALSE;
  1587.     ULONG palfmt;
  1588.     
  1589.     APTR newpalette;
  1590.  
  1591.  
  1592.     ObtainSemaphore(&pic->semaphore);
  1593.  
  1594.  
  1595.     pentab = (UBYTE *) GetTagData(GGFX_PenTable, NULL, tags);
  1596.     palfmt = GetTagData(GGFX_PaletteFormat, PALFMT_RGB8, tags);
  1597.  
  1598.  
  1599.     if (newpalette = CreatePalette(RND_HSType, 
  1600.         pic->hstype == HSTYPE_UNDEFINED ? DEFAULT_PALETTE_HSTYPE : pic->hstype,
  1601.         RND_RMHandler, MemHandler, TAG_DONE))
  1602.     {
  1603.         ULONG numcolors;
  1604.         int i;
  1605.  
  1606.         if (palfmt == PALFMT_PALETTE)
  1607.         {
  1608.             if (numcolors = GetPaletteAttrs(palette, NULL))
  1609.             {
  1610.                 ULONG rgb;
  1611.                 for (i = 0; i < numcolors; ++i)
  1612.                 {
  1613.                     ExportPalette(palette, &rgb, RND_FirstColor, i,
  1614.                         RND_NumColors, 1, TAG_DONE);
  1615.                     ImportPalette(newpalette, &rgb, 1, RND_FirstColor, i,
  1616.                         RND_NewPalette, FALSE, TAG_DONE);
  1617.                 }
  1618.                 success = TRUE;
  1619.             }
  1620.         }
  1621.         else
  1622.         {
  1623.             if (numcolors = GetTagData(GGFX_NumColors, 0, tags))
  1624.             {
  1625.                 ULONG *palptr;
  1626.                 for (i = 0; i < numcolors; ++i)
  1627.                 {
  1628.                     switch (palfmt)
  1629.                     {
  1630.                         case PALFMT_RGB32:
  1631.                             palptr = ((ULONG *)palette) + 3 * i;
  1632.                             break;
  1633.     
  1634.                         case PALFMT_RGB4:
  1635.                             palptr = (ULONG *) (((UWORD *)palette) + i);
  1636.                             break;
  1637.  
  1638.                         default:
  1639.                         case PALFMT_RGB8:
  1640.                             palptr = ((ULONG *)palette) + i;
  1641.                             break;
  1642.                     }                                
  1643.                     ImportPalette(newpalette, palptr, 1, RND_PaletteFormat, palfmt,
  1644.                         RND_FirstColor, i, RND_NewPalette, FALSE, TAG_DONE);
  1645.                 }
  1646.                 success = TRUE;
  1647.             }
  1648.         }
  1649.     }
  1650.  
  1651.  
  1652.     if (success)
  1653.     {
  1654.         success = FALSE;
  1655.  
  1656.         if (PrepareDrawing(pic))
  1657.         {
  1658.             if (!pic->directdraw)
  1659.             {
  1660.                 if (pic->pixelformat == PIXFMT_0RGB_32)
  1661.                 {
  1662.                     if (ExtractAlphaArray(pic))
  1663.                     {
  1664.                         if (Render((APTR)pic->array, pic->width, pic->height,
  1665.                             pic->array, newpalette, RND_PenTable, pentab, TAG_DONE) == REND_SUCCESS)
  1666.                         {
  1667.                             success = TRUE;
  1668.                         }
  1669.                     }
  1670.                 }
  1671.                 else
  1672.                 {
  1673.                     if (ConvertChunky(pic->array, pic->palette, pic->width, pic->height,
  1674.                         pic->array, newpalette, RND_PenTable, pentab, TAG_DONE) == CONV_SUCCESS)
  1675.                     {
  1676.                         success = TRUE;
  1677.                     }
  1678.                 }
  1679.             }
  1680.         }
  1681.     }
  1682.  
  1683.     if (success)
  1684.     {
  1685.         pic->pixelformat = PIXFMT_CHUNKY_CLUT;
  1686.  
  1687.         if (pic->palette)
  1688.         {
  1689.             DeletePalette(pic->palette);
  1690.         }
  1691.  
  1692. /*
  1693.         if (pentab)
  1694.         {
  1695.             int i;
  1696.         
  1697.             for (i = 0; i < 256; ++i)
  1698.             {
  1699.                 pic->pentab[i] = pentab[i];
  1700.             }
  1701.             pic->pentabptr = pentab;
  1702.         }
  1703. */
  1704.  
  1705.         pic->palette = newpalette;
  1706.     }
  1707.     else
  1708.     {
  1709.         if (newpalette)
  1710.         {
  1711.             DeletePalette(newpalette);
  1712.         }
  1713.     }
  1714.  
  1715.  
  1716.  
  1717.     ReleaseSemaphore(&pic->semaphore);
  1718.  
  1719.     return success;
  1720. }
  1721.  
  1722.  
  1723. /*--------------------------------------------------------------------
  1724.  
  1725.     Texture (pic1,pic2,*coordinates,tags)
  1726.  
  1727.     Tags:
  1728.         GGFX_DestWidth            (Ziel)
  1729.         GGFX_DestHeight
  1730.         GGFX_DestX
  1731.         GGFX_DestY
  1732.  
  1733.         GGFX_SourceWidth        (Textur)
  1734.         GGFX_SourceHeight
  1735.         GGFX_SourceX
  1736.         GGFX_SourceY
  1737.  
  1738. --------------------------------------------------------------------*/
  1739.  
  1740. ULONG PIC_Texture(PIC *pic, PIC *texpic, WORD *coords, TAGLIST tags)
  1741. {
  1742.     BOOL success = TRUE;
  1743.  
  1744.     UWORD destwidth, destheight, destx, desty;
  1745.     UWORD sourcewidth, sourceheight, sourcex, sourcey;
  1746.  
  1747.     ObtainSemaphore(&pic->semaphore);
  1748.     ObtainSemaphore(&texpic->semaphore);
  1749.  
  1750.     destwidth = GetTagData(GGFX_DestWidth, pic->width, tags);
  1751.     destheight = GetTagData(GGFX_DestHeight, pic->height, tags);
  1752.     destx = GetTagData(GGFX_DestX, 0, tags);
  1753.     desty = GetTagData(GGFX_DestY, 0, tags);
  1754.  
  1755.     sourcewidth = GetTagData(GGFX_SourceWidth, texpic->width, tags);
  1756.     sourceheight = GetTagData(GGFX_SourceHeight, texpic->height, tags);
  1757.     sourcex = GetTagData(GGFX_SourceX, 0, tags);
  1758.     sourcey = GetTagData(GGFX_SourceY, 0, tags);
  1759.  
  1760.     if (PrepareDrawing(pic))
  1761.     {
  1762.         if (PrepareDrawing(texpic))
  1763.         {
  1764.             if (pic->pixelformat != texpic->pixelformat)
  1765.             {
  1766.                 success = FALSE;
  1767.         
  1768.                 if (texpic->pixelformat == PIXFMT_CHUNKY_CLUT)
  1769.                 {
  1770.                     success = PIC_Render(texpic, PIXFMT_0RGB_32, NULL);
  1771.                 }    
  1772.         
  1773.                 if (!success)
  1774.                 {
  1775.                     if (pic->pixelformat == PIXFMT_CHUNKY_CLUT)
  1776.                     {
  1777.                         success = PIC_Render(pic, PIXFMT_0RGB_32, NULL);
  1778.                     }    
  1779.                 }
  1780.         
  1781.                 if (!success)
  1782.                 {
  1783.                     if (texpic->pixelformat == PIXFMT_0RGB_32)
  1784.                     {
  1785.                         success = PIC_RenderPalette(texpic, pic->palette,
  1786.                             GGFX_PaletteFormat, PALFMT_PALETTE, TAG_DONE);
  1787.                     }    
  1788.                 }
  1789.         
  1790.                 if (!success)
  1791.                 {
  1792.                     if (pic->pixelformat == PIXFMT_0RGB_32)
  1793.                     {
  1794.                         success = PIC_RenderPalette(pic, texpic->palette,
  1795.                             GGFX_PaletteFormat, PALFMT_PALETTE, TAG_DONE);
  1796.                     }
  1797.                 }
  1798.             }
  1799.         }
  1800.     }
  1801.  
  1802.     if (success)
  1803.     {
  1804.         APTR texengine;
  1805.         UBYTE *source = (UBYTE *)texpic->array + (sourcex + sourcey * texpic->width) * PIXELSIZE(texpic->pixelformat);
  1806.         UBYTE *dest = (UBYTE *)pic->array + (destx + desty * pic->width) * PIXELSIZE(pic->pixelformat);
  1807.  
  1808.         success = FALSE;
  1809.  
  1810.         if (texengine = CreateScaleEngine(sourcewidth, sourceheight, 
  1811.             destwidth, destheight, RND_RMHandler, MemHandler,
  1812.             RND_DestCoordinates, coords, RND_PixelFormat, pic->pixelformat, TAG_DONE))
  1813.         {
  1814.             Scale(texengine, (APTR) source, (APTR) dest, 
  1815.                 RND_SourceWidth, texpic->width,
  1816.                 RND_DestWidth, pic->width, TAG_DONE);
  1817.             DeleteScaleEngine(texengine);
  1818.             success = TRUE;
  1819.         }
  1820.     }
  1821.  
  1822.     
  1823.     ReleaseSemaphore(&texpic->semaphore);
  1824.     ReleaseSemaphore(&pic->semaphore);
  1825.  
  1826.     return success;
  1827. }
  1828.  
  1829.  
  1830. /*--------------------------------------------------------------------
  1831.  
  1832.     Set (pic1,RGB,tags)
  1833.  
  1834.     Tags:
  1835.         GGFX_DestWidth            (Ziel)
  1836.         GGFX_DestHeight
  1837.         GGFX_DestX
  1838.         GGFX_DestY
  1839.  
  1840. --------------------------------------------------------------------*/
  1841.  
  1842. ULONG PIC_Set(PIC *pic, ULONG rgb, TAGLIST tags)
  1843. {
  1844.     BOOL success = FALSE;
  1845.  
  1846.     UWORD destwidth, destheight, destx, desty;
  1847.  
  1848.     ObtainSemaphore(&pic->semaphore);
  1849.  
  1850.     destwidth = GetTagData(GGFX_DestWidth, pic->width, tags);
  1851.     destheight = GetTagData(GGFX_DestHeight, pic->height, tags);
  1852.     destx = GetTagData(GGFX_DestX, 0, tags);
  1853.     desty = GetTagData(GGFX_DestY, 0, tags);
  1854.  
  1855.     if (PrepareDrawing(pic))
  1856.     {
  1857.         switch (pic->pixelformat)
  1858.         {
  1859.             case PIXFMT_CHUNKY_CLUT:
  1860.             {
  1861.                 UBYTE *p = (UBYTE *)pic->array + (destx + desty * pic->width);
  1862.  
  1863.                 UBYTE pen;
  1864.                 
  1865.                 if (pic->directdraw)
  1866.                 {
  1867.                     pen = pic->directdraw->mainpentab[BestPen(pic->directdraw->mainpalette, rgb)];
  1868.                 }
  1869.                 else
  1870.                 {
  1871.                     pen = BestPen(pic->palette, rgb);
  1872.                 }
  1873.  
  1874.                 if (destwidth != pic->width)
  1875.                 {
  1876.                     int i;
  1877.                     for (i = 0; i < destheight; ++i)
  1878.                     {
  1879.                         TurboFillMem(p, destwidth, pen);
  1880.                         p += pic->width;
  1881.                     }
  1882.                 }
  1883.                 else
  1884.                 {
  1885.                     TurboFillMem(p, destwidth*destheight, pen);
  1886.                 }
  1887.                 break;
  1888.             }
  1889.             
  1890.             case PIXFMT_0RGB_32:
  1891.             {
  1892.                 ULONG *p = (ULONG *)pic->array + (destx + desty * pic->width);
  1893.                 int x,y;
  1894.                 
  1895.                 for (y = 0; y < destheight; ++y)
  1896.                 {
  1897.                     for (x = 0; x < destwidth; ++x)
  1898.                     {
  1899.                         *p++ = rgb;
  1900.                     }
  1901.                     p += pic->width - destwidth;
  1902.                 }
  1903.                 break;
  1904.             }
  1905.         }
  1906.         success = TRUE;            
  1907.     }
  1908.     
  1909.     ReleaseSemaphore(&pic->semaphore);
  1910.  
  1911.     return success;
  1912. }
  1913.  
  1914.  
  1915.  
  1916. /*--------------------------------------------------------------------
  1917.  
  1918.     Insert (destpic, sourcepic, tags)
  1919.  
  1920.     Tags:
  1921.         GGFX_SourceWidth        (Quelle)
  1922.         GGFX_SourceHeight
  1923.         GGFX_SourceX
  1924.         GGFX_SourceY
  1925.         GGFX_DestWidth            (Ziel)
  1926.         GGFX_DestHeight
  1927.         GGFX_DestX
  1928.         GGFX_DestY
  1929.  
  1930. --------------------------------------------------------------------*/
  1931.  
  1932. ULONG PIC_Insert(PIC *pic, PIC *sourcepic, TAGLIST tags)
  1933. {
  1934.     BOOL success = FALSE;
  1935.  
  1936.     UWORD destwidth, destheight, destx, desty;
  1937.     UWORD sourcewidth, sourceheight, sourcex, sourcey;
  1938.  
  1939.     ObtainSemaphore(&pic->semaphore);
  1940.     ObtainSemaphore(&sourcepic->semaphore);
  1941.  
  1942.     destwidth = GetTagData(GGFX_DestWidth, pic->width, tags);
  1943.     destheight = GetTagData(GGFX_DestHeight, pic->height, tags);
  1944.     destx = GetTagData(GGFX_DestX, 0, tags);
  1945.     desty = GetTagData(GGFX_DestY, 0, tags);
  1946.  
  1947.     sourcewidth = GetTagData(GGFX_SourceWidth, sourcepic->width, tags);
  1948.     sourceheight = GetTagData(GGFX_SourceHeight, sourcepic->height, tags);
  1949.     sourcex = GetTagData(GGFX_SourceX, 0, tags);
  1950.     sourcey = GetTagData(GGFX_SourceY, 0, tags);
  1951.  
  1952.  
  1953.     if (pic->directdraw && sourcepic->directdraw)
  1954.     {
  1955.         if (pic->directdraw == sourcepic->directdraw)
  1956.         {
  1957.             success = TRUE;
  1958.         }
  1959.     }
  1960.     
  1961.  
  1962.     if (!success)
  1963.     {
  1964.         if (PrepareDrawing(pic))
  1965.         {
  1966.             if (PrepareDrawing(sourcepic))
  1967.             {
  1968.                 PIC_Render(sourcepic, PIXFMT_0RGB_32, NULL);
  1969.                 PIC_Render(pic, PIXFMT_0RGB_32, NULL);
  1970.                 
  1971.                 success = (sourcepic->pixelformat == PIXFMT_0RGB_32 && pic->pixelformat == PIXFMT_0RGB_32);
  1972.             }
  1973.         }
  1974.     }
  1975.  
  1976.  
  1977.     if (success)
  1978.     {    
  1979.         UBYTE *source = (UBYTE *)sourcepic->array + (sourcex + sourcey * sourcepic->width) * PIXELSIZE(sourcepic->pixelformat);
  1980.         UBYTE *dest = (UBYTE *)pic->array + (destx + desty * pic->width) * PIXELSIZE(pic->pixelformat);
  1981.         success = FALSE;
  1982.  
  1983.         if (destwidth != sourcewidth || destheight != sourceheight)
  1984.         {
  1985.             APTR scaleengine;
  1986.  
  1987.             if (scaleengine = CreateScaleEngine(sourcewidth, sourceheight,
  1988.                         destwidth, destheight, RND_RMHandler, MemHandler, 
  1989.                         RND_PixelFormat, pic->pixelformat, TAG_DONE))
  1990.             {
  1991.                 success = (Scale(scaleengine, source, dest,
  1992.                                 RND_SourceWidth, sourcepic->width,
  1993.                                 RND_DestWidth, pic->width, TAG_DONE) == CONV_SUCCESS);
  1994.             
  1995.                 DeleteScaleEngine(scaleengine);
  1996.             }
  1997.         }
  1998.         else
  1999.         {
  2000.             int i;
  2001.             int pixelsize = PIXELSIZE(pic->pixelformat);
  2002.  
  2003.             for (i = 0; i < destheight; ++i)
  2004.             {
  2005.                 TurboCopyMem(source, dest, pixelsize * destwidth);
  2006.                 source += pixelsize * sourcepic->width;
  2007.                 dest += pixelsize * pic->width;
  2008.             }
  2009.  
  2010.             success = TRUE;
  2011.         }
  2012.  
  2013.     }
  2014.  
  2015.     ReleaseSemaphore(&sourcepic->semaphore);
  2016.     ReleaseSemaphore(&pic->semaphore);
  2017.  
  2018.     return success;
  2019. }
  2020.  
  2021.  
  2022. /*--------------------------------------------------------------------
  2023.  
  2024.     FlipX (pic, tags)
  2025.     FlipY (pic, tags)
  2026.     
  2027.         GGFX_DestWidth
  2028.         GGFX_DestHeight
  2029.         GGFX_DestX
  2030.         GGFX_DestY
  2031.  
  2032. --------------------------------------------------------------------*/
  2033.  
  2034. ULONG PIC_FlipX(PIC *pic, TAGLIST tags)
  2035. {
  2036.     BOOL success = TRUE;
  2037.  
  2038.     UWORD destwidth, destheight, destx, desty;
  2039.  
  2040.     ObtainSemaphore(&pic->semaphore);
  2041.  
  2042.     destwidth = GetTagData(GGFX_DestWidth, pic->width, tags);
  2043.     destheight = GetTagData(GGFX_DestHeight, pic->height, tags);
  2044.     destx = GetTagData(GGFX_DestX, 0, tags);
  2045.     desty = GetTagData(GGFX_DestY, 0, tags);
  2046.  
  2047.     if (PrepareDrawing(pic))
  2048.     {
  2049.         if (InsertAlphaArray(pic))
  2050.         {
  2051.             UBYTE *array = (UBYTE *)pic->array + (destx + desty * pic->width) * PIXELSIZE(pic->pixelformat);
  2052.             int x, y;
  2053.     
  2054.             if (pic->pixelformat == PIXFMT_CHUNKY_CLUT)
  2055.             {
  2056.                 UBYTE *s, *d, t;
  2057.     
  2058.                 for (y = 0; y < destheight; ++y)
  2059.                 {
  2060.                     s = array;
  2061.                     d = array + destwidth;
  2062.                     for (x = 0; x < destwidth/2; ++x)
  2063.                     {
  2064.                         t = *s;
  2065.                         *s++ = *(--d);
  2066.                         *d = t;
  2067.                     }
  2068.                     array += pic->width;
  2069.                 }        
  2070.             }
  2071.             else
  2072.             {
  2073.                 ULONG *s, *d, t;
  2074.     
  2075.                 for (y = 0; y < destheight; ++y)
  2076.                 {
  2077.                     s = (ULONG *) array;
  2078.                     d = ((ULONG *) array) + destwidth;
  2079.                     for (x = 0; x < destwidth/2; ++x)
  2080.                     {
  2081.                         t = *s;
  2082.                         *s++ = *(--d);
  2083.                         *d = t;
  2084.                     }
  2085.                     array += pic->width * 4;
  2086.                 }        
  2087.             }
  2088.         }
  2089.     }
  2090.  
  2091.     ReleaseSemaphore(&pic->semaphore);
  2092.  
  2093.     return success;
  2094. }
  2095.  
  2096.  
  2097. ULONG PIC_FlipY(PIC *pic, TAGLIST tags)
  2098. {
  2099.     BOOL success = TRUE;
  2100.  
  2101.     UWORD destwidth, destheight, destx, desty;
  2102.  
  2103.     ObtainSemaphore(&pic->semaphore);
  2104.  
  2105.     destwidth = GetTagData(GGFX_DestWidth, pic->width, tags);
  2106.     destheight = GetTagData(GGFX_DestHeight, pic->height, tags);
  2107.     destx = GetTagData(GGFX_DestX, 0, tags);
  2108.     desty = GetTagData(GGFX_DestY, 0, tags);
  2109.  
  2110.     if (PrepareDrawing(pic))
  2111.     {
  2112.         if (InsertAlphaArray(pic))
  2113.         {
  2114.             UBYTE *array = (UBYTE *)pic->array + (destx + desty * pic->width) * PIXELSIZE(pic->pixelformat);
  2115.             int x, y;
  2116.     
  2117.             if (pic->pixelformat == PIXFMT_CHUNKY_CLUT)
  2118.             {
  2119.                 UBYTE *s, *d, t;
  2120.     
  2121.                 for (y = 0; y < destheight/2; ++y)
  2122.                 {
  2123.                     s = array + y * pic->width;
  2124.                     d = array + (destheight - y - 1) * pic->width;
  2125.                     
  2126.                     for (x = 0; x < destwidth; ++x)
  2127.                     {
  2128.                         t = *s;
  2129.                         *s++ = *d;
  2130.                         *d++ = t;
  2131.                     }
  2132.                 }        
  2133.             }
  2134.             else
  2135.             {
  2136.                 ULONG *s, *d, t;
  2137.  
  2138.                 for (y = 0; y < destheight/2; ++y)
  2139.                 {
  2140.                     s = ((ULONG *) array) + y * pic->width;
  2141.                     d = ((ULONG *) array) + (destheight - y - 1) * pic->width;
  2142.                     
  2143.                     for (x = 0; x < destwidth; ++x)
  2144.                     {
  2145.                         t = *s;
  2146.                         *s++ = *d;
  2147.                         *d++ = t;
  2148.                     }
  2149.                 }        
  2150.             }
  2151.         }
  2152.     }
  2153.  
  2154.     ReleaseSemaphore(&pic->semaphore);
  2155.  
  2156.     return success;
  2157. }
  2158.  
  2159. /*--------------------------------------------------------------------
  2160.  
  2161.     ULONG CheckDither (pic, drawhandle, tags)
  2162.  
  2163. --------------------------------------------------------------------*/
  2164.  
  2165. ULONG PIC_CheckDither(PIC *pic, DRAWHANDLE *dh, TAGLIST tags)
  2166. {
  2167.     BOOL dithers = FALSE;
  2168.  
  2169.     ObtainSemaphore(&pic->semaphore);
  2170.  
  2171.     if (!dh->rasthandle->truecolor)
  2172.     {
  2173.         if (PrepareDrawing(pic))
  2174.         {
  2175.             if (GetDitherMode(dh, pic->array, pic->palette,
  2176.                 pic->width, pic->height, pic->pixelformat, pic->width, DITHERMODE_FS,
  2177.                 TRUE /*dh->autodither*/) == DITHERMODE_FS)
  2178.             {
  2179.                 dithers = TRUE;
  2180.             }
  2181.         }
  2182.     }
  2183.  
  2184.     ReleaseSemaphore(&pic->semaphore);
  2185.     
  2186.     return (ULONG) dithers;
  2187. }
  2188.  
  2189.  
  2190. /*--------------------------------------------------------------------
  2191.  
  2192.     Negative (pic, tags)
  2193.     
  2194.         GGFX_DestWidth
  2195.         GGFX_DestHeight
  2196.         GGFX_DestX
  2197.         GGFX_DestY
  2198.  
  2199. --------------------------------------------------------------------*/
  2200.  
  2201. ULONG PIC_Negative(PIC *pic, TAGLIST tags)
  2202. {
  2203.     BOOL success = TRUE;
  2204.  
  2205.     UWORD destwidth, destheight, destx, desty;
  2206.  
  2207.     ObtainSemaphore(&pic->semaphore);
  2208.  
  2209.     destwidth = GetTagData(GGFX_DestWidth, pic->width, tags);
  2210.     destheight = GetTagData(GGFX_DestHeight, pic->height, tags);
  2211.     destx = GetTagData(GGFX_DestX, 0, tags);
  2212.     desty = GetTagData(GGFX_DestY, 0, tags);
  2213.  
  2214.     if (InsertAlphaArray(pic))
  2215.     {
  2216.         if (PIC_Render(pic, PIXFMT_0RGB_32, NULL))
  2217.         {
  2218.             ULONG *p = ((ULONG *) pic->array) + destx + desty * pic->width;
  2219.             ULONG *pp, rgb; 
  2220.             int x,y;
  2221.  
  2222.             for (y = 0; y < destheight; ++y)
  2223.             {
  2224.                 pp = p;
  2225.  
  2226.                 for (x = 0; x < destwidth; ++x)
  2227.                 {
  2228.                     rgb = *pp;
  2229.                     *pp++ = (rgb & 0xff000000) | (~rgb & 0x00ffffff);
  2230.                 }
  2231.                 
  2232.                 p += pic->width;
  2233.             }
  2234.     
  2235.             success = TRUE;    
  2236.         }
  2237.     }
  2238.  
  2239.  
  2240.     ReleaseSemaphore(&pic->semaphore);
  2241.  
  2242.     return success;
  2243. }
  2244.  
  2245.  
  2246.  
  2247.  
  2248.  
  2249.  
  2250. void AutoCutChunky(char *array, int w, int h, int totalwidth,
  2251.     int *neww, int *newh, int *xoffs, int *yoffs)
  2252. {
  2253.     char chunky, *p;
  2254.     int i;
  2255. //    int x = 0, y = 0;
  2256.     
  2257.     int left, top, right, bottom;
  2258.     int numfound;
  2259.     int found = 0;
  2260.     
  2261.     left = 0;
  2262.     top = 0;
  2263.     right = w - 1;
  2264.     bottom = h - 1;
  2265.  
  2266.     do
  2267.     {
  2268.         numfound = 0;
  2269.  
  2270.  
  2271.         //    top
  2272.  
  2273.         if (!(found & 1) && h > 2)
  2274.         do
  2275.         {        
  2276.             p = array + left + top * totalwidth;
  2277.             chunky = *p;
  2278.             i = 0;
  2279.             while (i < w)
  2280.             {
  2281.                 if (*p != chunky) break;
  2282.                 p++;
  2283.                 i++;            
  2284.             }
  2285.             if (i == w)
  2286.             {
  2287.                 top++;
  2288.                 numfound++;
  2289.                 found |= 1;
  2290.                 if (--h < 3) break;
  2291.             }
  2292.         } while (i == w);
  2293.  
  2294.         //    right
  2295.  
  2296.         if (!(found & 2) && w > 2)
  2297.         do
  2298.         {    
  2299.             p = array + right + top * totalwidth;
  2300.             chunky = *p;
  2301.             i = 0;
  2302.             while (i < h)
  2303.             {
  2304.                 if (*p != chunky) break;
  2305.                 p += totalwidth;
  2306.                 i++;            
  2307.             }
  2308.             if (i == h)
  2309.             {
  2310.                 right--;
  2311.                 numfound++;
  2312.                 found |= 2;
  2313.                 if (--w < 3) break;
  2314.             }
  2315.         } while (i == h);
  2316.  
  2317.         //    bottom
  2318.  
  2319.         if (!(found & 4) && h > 2)
  2320.         do
  2321.         {    
  2322.             p = array + left + bottom * totalwidth;
  2323.             chunky = *p;
  2324.             i = 0;
  2325.             while (i < w)
  2326.             {
  2327.                 if (*p != chunky) break;
  2328.                 p++;
  2329.                 i++;            
  2330.             }
  2331.             if (i == w)
  2332.             {
  2333.                 bottom--;
  2334.                 numfound++;
  2335.                 found |= 4;
  2336.                 if (--h < 3) break;
  2337.             }
  2338.         } while (i == w);
  2339.  
  2340.         //    left
  2341.  
  2342.         if (!(found & 8) && w > 2)
  2343.         do
  2344.         {    
  2345.             p = array + left + top * totalwidth;
  2346.             chunky = *p;
  2347.             i = 0;
  2348.             while (i < h)
  2349.             {
  2350.                 if (*p != chunky) break;
  2351.                 p += totalwidth;
  2352.                 i++;            
  2353.             }
  2354.             if (i == h)
  2355.             {
  2356.                 left++;
  2357.                 numfound++;
  2358.                 found |= 8;
  2359.                 if (--w < 3) break;
  2360.             }
  2361.         } while (i == h);
  2362.  
  2363.     } while (numfound > 0 && w > 2 && h > 2);
  2364.  
  2365.     *neww = right - left + 1;
  2366.     *newh = bottom - top + 1;
  2367.     *xoffs = left;
  2368.     *yoffs = top;
  2369. }    
  2370.  
  2371.  
  2372. void AutoCutRGB(unsigned long *array, int w, int h, int totalwidth,
  2373.     int *neww, int *newh, int *xoffs, int *yoffs)
  2374. {
  2375.     unsigned long rgb, *p;
  2376.     int i;
  2377. //    int x = 0, y = 0;
  2378.     
  2379.     int left, top, right, bottom;
  2380.     int numfound;
  2381.     int found = 0;
  2382.     
  2383.     left = 0;
  2384.     top = 0;
  2385.     right = w - 1;
  2386.     bottom = h - 1;
  2387.  
  2388.     do
  2389.     {
  2390.         numfound = 0;
  2391.  
  2392.  
  2393.         //    top
  2394.  
  2395.         if (!(found & 1) && h > 2)
  2396.         do
  2397.         {        
  2398.             p = array + left + top * totalwidth;
  2399.             rgb = *p;
  2400.             i = 0;
  2401.             while (i < w)
  2402.             {
  2403.                 if (*p != rgb) break;
  2404.                 p++;
  2405.                 i++;            
  2406.             }
  2407.             if (i == w)
  2408.             {
  2409.                 top++;
  2410.                 numfound++;
  2411.                 found |= 1;
  2412.                 if (--h < 3) break;
  2413.             }
  2414.         } while (i == w);
  2415.  
  2416.  
  2417.         //    right
  2418.  
  2419.         if (!(found & 2) && w > 2)
  2420.         do
  2421.         {    
  2422.             p = array + right + top * totalwidth;
  2423.             rgb = *p;
  2424.             i = 0;
  2425.             while (i < h)
  2426.             {
  2427.                 if (*p != rgb) break;
  2428.                 p += totalwidth;
  2429.                 i++;            
  2430.             }
  2431.             if (i == h)
  2432.             {
  2433.                 right--;
  2434.                 numfound++;
  2435.                 found |= 2;
  2436.                 if (--w < 3) break;
  2437.             }
  2438.         } while (i == h);
  2439.  
  2440.  
  2441.         //    bottom
  2442.  
  2443.         if (!(found & 4) && h > 2)
  2444.         do
  2445.         {    
  2446.             p = array + left + bottom * totalwidth;
  2447.             rgb = *p;
  2448.             i = 0;
  2449.             while (i < w)
  2450.             {
  2451.                 if (*p != rgb) break;
  2452.                 p++;
  2453.                 i++;            
  2454.             }
  2455.             if (i == w)
  2456.             {
  2457.                 bottom--;
  2458.                 numfound++;
  2459.                 found |= 4;
  2460.                 if (--h < 3) break;
  2461.             }
  2462.         } while (i == w);
  2463.  
  2464.  
  2465.         //    left
  2466.  
  2467.         if (!(found & 8) && w > 2)
  2468.         do
  2469.         {    
  2470.             p = array + left + top * totalwidth;
  2471.             rgb = *p;
  2472.             i = 0;
  2473.             while (i < h)
  2474.             {
  2475.                 if (*p != rgb) break;
  2476.                 p += totalwidth;
  2477.                 i++;            
  2478.             }
  2479.             if (i == h)
  2480.             {
  2481.                 left++;
  2482.                 numfound++;
  2483.                 found |= 8;
  2484.                 if (--w < 3) break;
  2485.             }
  2486.         } while (i == h);
  2487.  
  2488.     } while (numfound > 0 && w > 2 && h > 2);
  2489.  
  2490.  
  2491.     *neww = right - left + 1;
  2492.     *newh = bottom - top + 1;
  2493.     *xoffs = left;
  2494.     *yoffs = top;
  2495. }    
  2496.  
  2497. /*--------------------------------------------------------------------
  2498.  
  2499.     AutoCrop (pic, tags)
  2500.     
  2501.         GGFX_SourceWidth
  2502.         GGFX_SourceHeight
  2503.         GGFX_SourceX
  2504.         GGFX_SourceY
  2505.  
  2506. --------------------------------------------------------------------*/
  2507.  
  2508. ULONG PIC_AutoCrop(PIC *pic, TAGLIST tags)
  2509. {
  2510.     BOOL success = FALSE;
  2511.  
  2512.     UWORD sourcewidth, sourceheight, sourcex, sourcey;
  2513.  
  2514.     ObtainSemaphore(&pic->semaphore);
  2515.  
  2516.     sourcewidth = GetTagData(GGFX_SourceWidth, pic->width, tags);
  2517.     sourceheight = GetTagData(GGFX_SourceHeight, pic->height, tags);
  2518.     sourcex = GetTagData(GGFX_SourceX, 0, tags);
  2519.     sourcey = GetTagData(GGFX_SourceY, 0, tags);
  2520.  
  2521.     if (PrepareDrawing(pic))
  2522.     {
  2523.         if (ExtractAlphaArray(pic))
  2524.         {
  2525.             int newx, newy, neww, newh;
  2526.  
  2527.             switch (pic->pixelformat)
  2528.             {
  2529.                 case PIXFMT_CHUNKY_CLUT:
  2530.  
  2531.                     AutoCutChunky((char *) pic->array + sourcex + sourcey * pic->width,
  2532.                         sourcewidth, sourceheight, pic->width,
  2533.                         &neww, &newh, &newx, &newy);
  2534.  
  2535.                     break;
  2536.  
  2537.                 case PIXFMT_0RGB_32:
  2538.  
  2539.                     AutoCutRGB((ULONG *) pic->array + sourcex + sourcey * pic->width,
  2540.                         sourcewidth, sourceheight, pic->width,
  2541.                         &neww, &newh, &newx, &newy);
  2542.                 
  2543.                     break;
  2544.             }
  2545.  
  2546.             PIC_Crop(pic, newx, newy, neww, newh, NULL);
  2547.     
  2548.             success = TRUE;
  2549.         }
  2550.     }
  2551.  
  2552.  
  2553.     ReleaseSemaphore(&pic->semaphore);
  2554.  
  2555.     return success;
  2556. }
  2557.